// 导入 MySQL 模块
const mysql = require("mysql");
const util = require("../../common/util");
const config = require("../../common/config");

// 创建 MySQL 连接池
const pool = require("../../common/util");


class ItemDB {
  /**
   * @constructor
   * @private
   */
  constructor() {
    this.instance = null;
    this.pool = pool;
  }

  /**
   * 创建 ItemDB 对象
   * @returns {ItemDB} ItemDB 实例
   */
  static getInstance() {
    if (!this.instance) {
      this.instance = new ItemDB();
    }
    return this.instance;
  }
}

/**
 * 获取指定ID的物品
 * @param {Number} itemId 物品ID
 * @returns {Promise<Object>} 物品详情
 */
ItemDB.prototype.find = async function (itemId) {
  try {
    // 构造查询物品的 SQL 语句
    let sql = `SELECT * FROM items WHERE id = ?`;
    // 提取物品ID作为参数
    let params = [itemId];

    // 使用 query 函数执行 SQL 查询操作
    let result = await this.pool.query(sql, params);

    // 返回查询结果
    return result;
  } catch (err) {
    // 在出现错误时抛出异常
    throw err;
  }
};


/**
 * 获取物品列表
 * @param {Number} [limit=-1] 数量限制
 * @param {Number} [offset=-1] 分页偏移
 * @returns {Promise<Array<Object>>} 物品列表
 */
ItemDB.prototype.findAll = async function (limit = -1, offset = -1) {
  try {
    let sql = "SELECT * FROM items ORDER BY id";
    let params = [];
    if (limit !== -1) {
      sql += " LIMIT ?";
      params.push(limit);

      if (offset !== -1) {
        sql += " OFFSET ?";
        params.push(offset);
      }
    }

    // 使用 query 函数执行 SQL 查询操作
    let result = await this.pool.query(sql, params);

    // 返回查询结果
    return result;
  } catch (err) {
    // 在出现错误时抛出异常
    throw err;
  }
};

/**
 * 获取个人物品列表
 * @param {Number} [limit=-1] 数量限制
 * @param {Number} [offset=-1] 分页偏移
 * @returns {Promise<Array<Object>>} 物品列表
 */
ItemDB.prototype.findSelfAll = async function (userId, limit = -1, offset = -1) {
  try {
    // 构造查询物品列表的 SQL 语句
    let sql = "SELECT * FROM items WHERE owner_id = ? ORDER BY id";
    let params = [userId];

    if (limit !== -1) {
      sql += " LIMIT ?";
      params.push(limit);

      if (offset !== -1) {
        sql += " OFFSET ?";
        params.push(offset);
      }
    }

    // 使用 query 函数执行 SQL 查询操作
    let result = await this.pool.query(sql, params);

    // 返回查询结果
    return result;
  } catch (err) {
    // 在出现错误时抛出异常
    throw err;
  }
};
/**
 * 新增物品
 * @param {Object} item 物品数据
 * @returns {Promise<Number>} 新增物品的自增ID
 */
ItemDB.prototype.add = async function (item) {
  try {
    // 构造插入物品的 SQL 语句
    let sql = `INSERT INTO items (
      name, description, category, orderId,owner_id,
      quantity, barcode, image_path, retrieve_time
    ) VALUES (
      ?, ?, ?, ?, ?, 
      ?, ?, ?,?
    );`;

    // 提取物品数据作为参数
    let params = [
      item.name,
      item.description,
      item.category,
      item.orderId,
      item.ownerId,
      item.quantity,
      item.barcode,
      item.imagePath,
      item.retrieveTime
    ];

    // 使用 query 函数执行 SQL 插入操作
    let result = await this.pool.query(sql, params);

    // 返回自增ID
    return result.insertId;
  } catch (err) {
    // 在出现错误时抛出异常
    throw err;
  }
};

/**
 * 更新物品
 * @param {Object} item 包含要更新的物品数据的对象
 * @returns {Promise<Number>} 受影响的行数
 */
ItemDB.prototype.update = async function (item) {
  try {
    // 构造更新物品的 SQL 语句
    let sql = `UPDATE items SET
      name = ?,
      description = ?,
      category = ?,
      quantity = ?,
      image_path = ?
    WHERE id = ?;`;

    // 提取物品数据作为参数
    let params = [
      item.name,
      item.description,
      item.category,
      item.quantity,
      item.imagePath,
      item.id // 最后一个是 WHERE 子句中的 id
    ];

    // 使用 query 函数执行 SQL 更新操作
    let result = await this.pool.query(sql, params);

    // 返回受影响的行数
    return result.affectedRows;
  } catch (err) {
    // 在出现错误时抛出异常
    throw err;
  }
};


/**
 * 删除物品
 * @param {Number} itemId 物品ID
 * @returns {Promise<Number>} 影响的记录数
 */
ItemDB.prototype.remove = async function (itemId) {
  try {
    // 构造删除物品的 SQL 语句
    let sql = `DELETE FROM items WHERE id = ?`;
    let params = [itemId];

    // 使用 query 函数执行 SQL 删除操作
    let result = await this.pool.query(sql, params);

    // 返回影响的记录数
    return result.affectedRows;
  } catch (err) {
    // 在出现错误时抛出异常
    throw err;
  }
};

/**
 * 获取物品总数
 * @returns {Promise<Number>} 物品总数
 */
ItemDB.prototype.getCount = async function () {
  try {
    // 构造查询物品总数的 SQL 语句
    let sql = "SELECT COUNT(1) AS total FROM items";

    // 使用 query 函数执行 SQL 查询操作
    let result = await this.pool.query(sql);

    // 返回查询结果
    return result[0].total;
  } catch (err) {
    // 在出现错误时抛出异常
    throw err;
  }
};

/**
 * 获取个人物品总数
 * @returns {Promise<Number>} 物品总数
 */
ItemDB.prototype.getSelfCount = async function (userId) {
  try {
    let params = [userId];
    // 构造查询物品总数的 SQL 语句
    let sql = "SELECT COUNT(1) AS total FROM items where owner_id = ?";

    // 使用 query 函数执行 SQL 查询操作
    let result = await this.pool.query(sql, params);

    // 返回查询结果
    return result[0].total;
  } catch (err) {
    // 在出现错误时抛出异常
    throw err;
  }
};

/**
 * 搜索物品（按名称或描述模糊匹配）
 * @param {String} q 搜索关键词
 * @param {Number} [limit=-1] 数量限制
 * @param {Number} [offset=-1] 分页偏移
 * @returns {Promise<Array<Object>>} 搜索结果
 */
ItemDB.prototype.search = async function (q, limit = -1, offset = -1) {
  try {
    // 将 limit 和 offset 转换为数字，如果它们不能转换为数字，则使用默认值
    limit = Number(limit);
    offset = Number(offset);

    // 如果 limit 或 offset 转换后不是数字，则使用默认值
    if (isNaN(limit)) {
      limit = -1;
    }
    if (isNaN(offset)) {
      offset = -1;
    }

    // 确保 limit 是一个非负整数
    limit = Math.max(0, Math.floor(limit));

    // 构造搜索物品的 SQL 语句
    let sql = "SELECT * FROM items WHERE name LIKE ? OR description LIKE ?";
    let params = [`%${q}%`, `%${q}%`];

    // 如果需要，添加 LIMIT 和 OFFSET 子句
    if (limit !== -1) {
      sql += " LIMIT ?";
      params.push(limit);

      if (offset !== -1) {
        sql += " OFFSET ?";
        params.push(offset);
      }
    }

    // 使用 query 函数执行 SQL 查询操作
    let result = await this.pool.query(sql, params);

    // 返回查询结果
    return result;
  } catch (err) {
    // 在出现错误时抛出异常
    throw err;
  }
};


/**
 * 批量增加
 * @param {Object} items 
 * @returns {Promise<string>} JSON 
 */
ItemDB.prototype.batchAdd = async function (items) {
  try {
    // 检查 items 是否为数组
    if (!Array.isArray(items)) {
      throw new Error('items 必须是一个数组');
    }

    // 准备字段和值
    const fields = [
      "name",
      "description",
      "category",
      "owner_id",
      "orderId",
      "quantity",
      "barcode",
      "image_path",
    ];

    const values = items.map((item) => {
      // 过滤出有效的字段
      const itemValues = fields.map((field) => item[field] || null);
      return itemValues; // 返回一个数组，因为 MySQL 需要二维数组
    });

    // 构造批量插入的 SQL 语句
    const sql = `INSERT INTO items (${fields.join(", ")}) VALUES ?;`;

    // 使用 query 函数执行 SQL 批量插入操作
    const result = await this.pool.query(sql, [values]);

    // 返回受影响的行数
    return result.affectedRows;
  } catch (err) {
    util.err(err);
    throw err;
  }
};




ItemDB.prototype.batchUpdate = async function (items) {  
  const BATCH_SIZE = 50; // 根据您的需要设置批次大小  
  let updatedItems = []; // 用于存储更新结果的数组  
  
  for (let i = 0; i < items.length; i += BATCH_SIZE) {  
    const batch = items.slice(i, i + BATCH_SIZE);  
  
    // 对每个批次中的项目进行循环  
    for (const item of batch) {  
      const sql = "UPDATE items SET name = ?, description = ?, category = ?,quantity = ? WHERE id = ?";  
      const values = [item.name, item.description, item.category, item.status, item.quantity, item.id];  
  
      // 尝试更新单个项目  
      try {  
        const result = await this.pool.query(sql, values);  
        if (result.affectedRows > 0) {  
          // 如果受影响的行数大于0，说明更新成功  
          updatedItems.push({ id: item.id, success: true });  
        } else {  
          // 否则，可能是id不存在  
          updatedItems.push({ id: item.id, success: false, message: 'ID不存在，无法更新' });  
        }  
      } catch (error) {  
        // 捕获并处理错误  
        updatedItems.push({ id: item.id, success: false, message: error.message });  
      }  
    }  
  }  
  
  return updatedItems; // 返回更新结果的数组  
};  


/**
 * 关联查询
 */
ItemDB.prototype.getItemWithOwner = async function (itemId) {
  try {
    // 构造关联查询的 SQL 语句
    let sql = `
      SELECT items.*, users.username, users.email
      FROM items
      JOIN users ON items.owner_id = users.id
      WHERE items.id = ?
    `;
    let params = [itemId];

    // 使用 query 函数执行 SQL 查询操作
    let result = await this.pool.query(sql, params);

    // 返回查询结果
    return result[0];
  } catch (err) {
    // 在出现错误时抛出异常
    throw err;
  }
};

/**
 * 获取物品地址
 * @param {Number} itemId 物品ID
 * @returns {Promise<Object>} 物品及其地址信息
 */
ItemDB.prototype.getItemWithLocation = async function (itemId) {
  try {
    // 构造关联查询的 SQL 语句
    let sql = `
      SELECT items.*, storage_locations.*
      FROM items
      JOIN storage_locations ON items.location_id = storage_locations.id
      WHERE items.id = ?
    `;
    let params = [itemId];

    // 使用 query 函数执行 SQL 查询操作
    let result = await this.pool.query(sql, params);

    // 检查是否找到了对应的项
    if (result.length === 0) {
      throw new Error('没有找到具有给定 itemId 的项');
    }

    // 返回查询结果
    return result[0];
  } catch (err) {
    // 在出现错误时抛出异常
    throw err;
  }
};

/**
 * 按类别统计物品数量
 * @returns {Promise<Array<Object>>} 类别及其数量
 */
ItemDB.prototype.countByCategory = async function () {
  try {
    // 构造按类别统计物品数量的 SQL 语句
    let sql = `
      SELECT category, COUNT(*) as count
      FROM items
      GROUP BY category      ORDER BY category ASC
    `;

    // 使用 query 函数执行 SQL 查询操作
    let result = await this.pool.query(sql);

    // 返回查询结果
    return result;
  } catch (err) {
    // 在出现错误时抛出异常
    throw err;
  }
};

/**
 * 获取存储时间分布
 * @returns {Promise<Array<Object>>} 存储时间及其数量
 */
ItemDB.prototype.getStorageTimeDistribution = async function () {
  try {
    // 构造获取存储时间分布的 SQL 语句
    let sql = `
      SELECT DATE_FORMAT(storage_time, '%Y-%m') as period, COUNT(*) as count
      FROM items
      GROUP BY period
      ORDER BY period ASC
    `;

    // 使用 query 函数执行 SQL 查询操作
    let result = await this.pool.query(sql);

    // 返回查询结果
    return result;
  } catch (err) {
    // 在出现错误时抛出异常
    throw err;
  }
};


/**
 * 获取状态分布
 * @returns {Promise<Array<Object>>} 状态及其数量
 */
ItemDB.prototype.getStatusDistribution = async function () {
  try {
    // 构造获取状态分布的 SQL 语句
    let sql = `
      SELECT status, COUNT(*) as count
      FROM items
      GROUP BY status
      ORDER BY status ASC
    `;

    // 使用 query 函数执行 SQL 查询操作
    let result = await this.pool.query(sql);

    // 返回查询结果
    return result;
  } catch (err) {
    // 在出现错误时抛出异常
    throw err;
  }
};


module.exports = ItemDB;